/*
* LINUX:
* 	cflags:
* 	cxxglags:
* 	libs: -lpthread
* 	comments: (request for wsock32.lib or ws2_32.lib)
* 
* WINDOWS:
* 	cflags:
* 	cxxflags:
* 	libs: -lwsock32
* 	comments: (request for wsock32.lib or ws2_32.lib)
*/

#ifndef SERIAL_H_
#define SERIAL_H_

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>

#ifdef WIN32
#	include "wtypes.h"
#else
#	include <unistd.h>
#	include <fcntl.h>
#	include <termios.h>
#	include <sys/types.h>
#	include <sys/stat.h>
#	include <sys/ioctl.h>
#	include <linux/serial.h>
	static struct termios oldSettings;
	static struct termios newSettings;
	static struct serial_struct oldSerialInfo;
	static struct serial_struct newSerialInfo;
#endif

namespace comm {
	const int SERIAL_PORT_STRING_LENGTH = 128;
	
	class CSerialPort {
		public:
			enum EDataBits
			{
			    DATA_BITS_5_E = 5,
			    DATA_BITS_6_E = 6,
			    DATA_BITS_7_E = 7,
			    DATA_BITS_8_E = 8
			} m_enDataBits;

			enum EStopBits
			{
			    STOP_BITS_1_E = 0,
			    STOP_BITS_1P5_E = 1,
			    STOP_BITS_2_E = 2
			} m_enStopBits;

			enum EParity
			{
			    NO_PARITY_E = 0,
			    ODD_PARITY_E = 1,
			    EVEN_PARITY_E = 2,
			    MARK_PARITY_E = 3,
			    SPACE_PARITY_E = 4
			} m_enParity;

			enum EFlow
			{
			    FLOW_CONTROL_NONE_E = 0,
			    FLOW_CONTROL_CTS_E = 1
			} m_enFlow;

			char m_acPort[SERIAL_PORT_STRING_LENGTH];

			CSerialPort (unsigned int uiTxBufferSize = 1024, unsigned int uiRxBufferSize = 1024);
			virtual ~CSerialPort ();
			bool Open (const char * pcPort, int iBaud = 9600, EDataBits DataBits = DATA_BITS_8_E, EStopBits StopBits = STOP_BITS_1_E, EParity Parity = NO_PARITY_E, EFlow Flow = FLOW_CONTROL_NONE_E);
			bool Close (void);
			bool Read (void * pvBuffer, unsigned int uiNumOfBytes, unsigned long * pulNumOfBytesRead);
			bool ReadBlocking (void * pvBuffer, unsigned int uiNumOfBytes, unsigned long * pulNumOfBytesRead);
			bool Write (void * pvBuffer, unsigned int uiNumOfBytes);
			bool Reset (void);
		#ifdef WIN32
			bool GetOpenStatus (void) {
				if (m_hComm == NULL)
					return false;
				else
					return true;
			}
		#else
			bool GetOpenStatus (void) {
				if (m_hComm < 0)
					return false;
				else
					return true;
			}
		#endif
			static bool PortNumber2String (int iPortNumber, char * pcDestination);

		protected:
		#ifdef WIN32
			HANDLE m_hComm;
			COMMCONFIG m_CommConfig;
			DCB	m_Dcb;
			COMMTIMEOUTS m_CommTimeouts;
			COMSTAT m_ComStat;
			OVERLAPPED m_RxOverlapped;
			HANDLE m_RxEvent;
			OVERLAPPED m_ReadOverlapped;
			OVERLAPPED m_WriteOverlapped;
			HANDLE m_KillEvent;
		#else
			int m_hComm;
		#endif	
			int m_iBaud;
			unsigned int m_uiTxBufferSize;
			unsigned int m_uiRxBufferSize;
	};
}

#endif /* SERIAL_H_*/
